package com.furschina.service;

import java.text.MessageFormat;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cn.wooshai.core.service.local.AbstractService;

import com.furschina.dao.UserDao;
import com.furschina.model.User;
import com.furschina.vo.LoginUser;

@Service
@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
public class UserService extends AbstractService<UserDao, User> implements
		UserDetailsService {

	private MailSender mailSender;
	private SimpleMailMessage mailMessage;
	@Value("${mail.register.subject}")
	private String registerSubject;
	@Value("${mail.register.text}")
	private String registerText;
	@Value("${mail.password.subject}")
	private String passwordSubject;
	@Value("${mail.password.text}")
	private String passwordText;
	private PasswordEncoder passwordEncoder;
	
	/**
	 * @param passwordEncoder
	 *            the passwordEncoder to set
	 */
	public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
		this.passwordEncoder = passwordEncoder;
	}

	/**
	 * @param passwordSubject
	 *            the passwordSubject to set
	 */
	public void setPasswordSubject(String passwordSubject) {
		this.passwordSubject = passwordSubject;
	}

	/**
	 * @param passwordText
	 *            the passwordText to set
	 */
	public void setPasswordText(String passwordText) {
		this.passwordText = passwordText;
	}

	/**
	 * @param registerSubject
	 *            the registerSubject to set
	 */
	public void setRegisterSubject(String registerSubject) {
		this.registerSubject = registerSubject;
	}

	/**
	 * @param registerText
	 *            the registerText to set
	 */
	public void setRegisterText(String registerText) {
		this.registerText = registerText;
	}

	/**
	 * @param mailMessage
	 *            the mailMessage to set
	 */
	public void setMailMessage(SimpleMailMessage registerMailMessage) {
		this.mailMessage = registerMailMessage;
	}

	/**
	 * @param sender
	 *            the sender to set
	 */
	public void setMailSender(MailSender sender) {
		this.mailSender = sender;
	}

	/*
	 * ====================================牛B的分割线================================
	 */
	/**
	 * 用email登录，这年头都流行用email来登录了。。。
	 */
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		User user = StringUtils.indexOf(username, '@') > 0 ? this
				.findByEmail(username) : this.findByUsername(username);
		if (user == null) {
			throw new UsernameNotFoundException(username);
		}
		return new LoginUser(user);
	}

	/**
	 * 
	 * @param username
	 *            其实就是昵称。
	 * @return
	 */
	public User getUser(String username) {
		return dao.getByName(username);
	}

	@Transactional(propagation = Propagation.REQUIRED)
	public void createLocalUser(User user) {
		user.setPassword(passwordEncoder.encodePassword(user.getPassword(),
				user.getEmail()));
		user.genVerification(); // 生成华丽的激活码
		this.create(user);
		// sendMail(user, registerSubject, registerText);
	}

	/**
	 * @param user
	 */
	private void sendMail(User user, String subject, String text) {
		mailMessage.setSubject(subject);
		mailMessage.setText(MessageFormat.format(text, user.getUsername(),
				user.getVerification()));
		mailMessage.setTo(user.getEmail());
		mailSender.send(mailMessage);
	}

	/**
	 * 
	 * @param user
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public void modifyself(User user) {
		User u = this.findByPrimaryKey(user.getId());
		if (StringUtils.isNotEmpty(user.getAvatar())) {
			u.setAvatar(user.getAvatar());
		}
		if (!StringUtils.equals(user.getEmail(), u.getEmail())) {
			u.setEmail(user.getEmail());
			u.setVerified(false);
			u.genVerification();
		}
		if (StringUtils.isNotEmpty(user.getPassword())) {
			u.setPassword(passwordEncoder.encodePassword(user.getPassword(),
					u.getEmail()));
		}
		super.update(u);
	}

	public User findByEmail(String email) {
		User u = this.dao.getByEmail(email);
		if (u != null && !u.isVerified()) {
			throw new DisabledException("email not varified.");
		}
		return u;
	}

	public User findByUsername(String username) {
		return dao.getByName(username);
	}

	/**
	 * @param user
	 * @return
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public User active(User user) {
		User o = this.getUser(user.getUsername());
		if (user.getVerification().equals(o.getVerification())) {
			o.setEnabled(true);
			this.update(o);
		}
		return o;
	}

	@Transactional(propagation = Propagation.REQUIRED)
	public void resetPassword(User user) {
		User o = this.getUser(user.getUsername());
		o.genVerification();
		this.update(o);
		sendMail(o, passwordSubject, passwordText);
	}

	public User findByUseremail(String email) {
		return this.dao.getByEmail(email);
	}
}
